#ifndef XTHREAD_POOL_H
#define XTHREAD_POOL_H

#include<thread>
#include<queue>
#include<functional>
#include<future>
#include<condition_variable>
#include<vector>
#include<mutex>

namespace x
{
	//任务类
	class TaskBase{
	public:
		virtual ~TaskBase()=default;
		virtual void exec()=0;
		virtual bool IsExecSuccessful() const{return true};
	};
	//带返回值的任务类
	template<typename T>
	class FutureTask:public TaskBase{
	public:
		explicit FutureTask(std::function<T()> func):func_(std::move(func)){}

		void exec() override{
			try{
				if constexpr(std::is_void_v<T>){
					func_();
					promise_.set_value();
					exec_success_=true;
				}
				else{
					promise_.set_value(func_());
					exec_success_=true;
				}
			}
			catch(...){
				promise_.set_exception(std::current_exception);
				exec_success_=false;
			}
		}

		std::future<T> getfuture(){
			return promise_.get_future();
		}

		bool IsExecSuccessful() const{
			return exec_success_;
		}
	private:
		bool exec_success_=false;
		std::promise<T> promise_;
		std::function<T()> func_;
	};
	//等待队列满的处理策略
	enum class QueueFullPolicy{
		BLOCK,
		OVERWRITE,
		DISCARD
	};
	//线程池配置
	struct ThreadPoolCfg{
		size_t core_threads=std::thread::hardware_concurrency();
		size_t max_threads=std::thread::hardware_concurrency()*2;
		size_t max_queue_size=1000;
		std::chrono::milliseconds keep_alive_time{60000};
		QueueFullPolicy queue_full_policy=QueueFullPolicy::BLOCK;
	};

	//线程池状态
	enum class ThreadPoolState{
		RUNNING,
		PAUSED,
		SHUTTING_DOWN,
		FORCE_STOPPING,
		STOPPED
	};

	//线程池关闭选项
	enum class ShutDownOption{
		GRACEFUL,
		FORCE,
		TIMEOUT
	};


	class XthreadPool
	{
	public:
		explicit XthreadPool(int n);
		XthreadPool(const XthreadPool &)=delete;
		XthreadPool& operator=(const XthreadPool &)=delete;
		XthreadPool& operator=(const XthreadPool &&)=delete;
		XthreadPool(XthreadPool&&)=delete;
		
		bool Submit(std::unique_ptr<TaskBase> task);
		template <class T,class... Args>
		auto SubmitWithResult(T&& f,Args&&... args) 
			-> std::future<std::invoke_result_t<T,Args...>>;
		
		~XthreadPool();
	private:
		
		struct stats {
			size_t task_completed=0;
			size_t task_failed=0;
			double avg_task_time_ms=0;
			size_t active_threads=0;
		};
		
		void run();
		std::atomic<ThreadPoolState> state_{ThreadPoolState::RUNNING};
		uint32_t threadnums_;
		std::vector<std::thread> threads_;
		std::queue<std::function<void()>> work_queue_;
		std::mutex work_queue_lk;
		std::condition_variable work_queue_cond;
	
	
	
	
	
	};
	
	
	
	
	

	template <class T,class... Args>
	auto SubmitWithResult(T&& f,Args&&... args) -> std::future<class std::invoke_result_t<T,Args...>>
	{
		using ReturnType=typename std::invoke_result_t<T,Args...>;
		
		auto bound_func=std::bind(std::forward<T>(f),std::forward<Args>(args));

		auto task=std::make_unique<FutureTask<ReturnType>>(std::move(bound_func));
		auto future=task->getfuture();

		bool submitted=Submit(std::move(task));

		if(!submitted){
			std::promise<ReturnType> promise;
			promise.set_exception(std::make_exception_ptr(std::future_error(std::future_errc::broken_promise)));
			return promise.get_future();
		}

		return future;
	}
	//-------------C++17放弃std::result_of
	// std::future<typename std::result_of<T(Args...)>::type> 
	// XthreadPool::submit(T&& f,Args&&... args)
	// {
	// 		typedef typename std::result_of<T(Args...)>::type return_type;
	// 		typedef std::packaged_task<return_type()> task;
	// 		auto t=std::make_shared<task>(std::bind(std::forward<T>(f),std::forward<Args>(args)...));
	// 		auto res=t->get_future();
	// 		{
	// 			std::lock_guard<std::mutex> lg(work_queue_lk);
	// 			work_queue_.emplace([t]{(*t)();});
	// 		}
	// 		work_queue_cond.notify_one();
	// 		return res;
	// }

};
#endif
